home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / tcl / dist / tclAssem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-02  |  5.7 KB  |  208 lines

  1. /* 
  2.  * tclAssem.c --
  3.  *
  4.  *    This file contains procedures to help assemble Tcl commands
  5.  *    from an input source  where commands may arrive in pieces, e.g.
  6.  *    several lines of type-in corresponding to one command.
  7.  *
  8.  * Copyright 1990-1991 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /user6/ouster/tcl/RCS/tclAssem.c,v 1.9 92/07/02 09:14:05 ouster Exp $ SPRITE (Berkeley)";
  20. #endif /* not lint */
  21.  
  22. #include "tclInt.h"
  23.  
  24. /*
  25.  * The structure below is the internal representation for a command
  26.  * buffer, which is used to hold a piece of a command until a full
  27.  * command is available.  When a full command is available, it will
  28.  * be returned to the user, but it will also be retained in the buffer
  29.  * until the NEXT call to Tcl_AssembleCmd, at which point it will be
  30.  * removed.
  31.  */
  32.  
  33. typedef struct {
  34.     char *buffer;        /* Storage for command being assembled.
  35.                  * Malloc-ed, and grows as needed. */
  36.     int bufSize;        /* Total number of bytes in buffer. */
  37.     int bytesUsed;        /* Number of bytes in buffer currently
  38.                  * occupied (0 means there is not a
  39.                  * buffered incomplete command). */
  40. } CmdBuf;
  41.  
  42. /*
  43.  * Default amount of space to allocate in command buffer:
  44.  */
  45.  
  46. #define CMD_BUF_SIZE 100
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * Tcl_CreateCmdBuf --
  52.  *
  53.  *    Allocate and initialize a command buffer.
  54.  *
  55.  * Results:
  56.  *    The return value is a token that may be passed to
  57.  *    Tcl_AssembleCmd and Tcl_DeleteCmdBuf.
  58.  *
  59.  * Side effects:
  60.  *    Memory is allocated.
  61.  *
  62.  *----------------------------------------------------------------------
  63.  */
  64.  
  65. Tcl_CmdBuf
  66. Tcl_CreateCmdBuf()
  67. {
  68.     register CmdBuf *cbPtr;
  69.  
  70.     cbPtr = (CmdBuf *) ckalloc(sizeof(CmdBuf));
  71.     cbPtr->buffer = (char *) ckalloc(CMD_BUF_SIZE);
  72.     cbPtr->buffer[0] = '\0';
  73.     cbPtr->bufSize = CMD_BUF_SIZE;
  74.     cbPtr->bytesUsed = 0;
  75.     return (Tcl_CmdBuf) cbPtr;
  76. }
  77.  
  78. /*
  79.  *----------------------------------------------------------------------
  80.  *
  81.  * Tcl_DeleteCmdBuf --
  82.  *
  83.  *    Release all of the resources associated with a command buffer.
  84.  *    The caller should never again use buffer again.
  85.  *
  86.  * Results:
  87.  *    None.
  88.  *
  89.  * Side effects:
  90.  *    Memory is released.
  91.  *
  92.  *----------------------------------------------------------------------
  93.  */
  94.  
  95. void
  96. Tcl_DeleteCmdBuf(buffer)
  97.     Tcl_CmdBuf buffer;        /* Token for command buffer (return value
  98.                  * from previous call to Tcl_CreateCmdBuf). */
  99. {
  100.     register CmdBuf *cbPtr = (CmdBuf *) buffer;
  101.  
  102.     ckfree(cbPtr->buffer);
  103.     ckfree((char *) cbPtr);
  104. }
  105.  
  106. /*
  107.  *----------------------------------------------------------------------
  108.  *
  109.  * Tcl_AssembleCmd --
  110.  *
  111.  *    This is a utility procedure to assist in situations where
  112.  *    commands may be read piece-meal from some input source.  Given
  113.  *    some input text, it adds the text to an input buffer and returns
  114.  *    whole commands when they are ready.
  115.  *
  116.  * Results:
  117.  *    If the addition of string to any currently-buffered information
  118.  *    results in one or more complete Tcl commands, then the return value
  119.  *    is a pointer to the complete command(s).  The command value will
  120.  *    only be valid until the next call to this procedure with the
  121.  *    same buffer.  If the addition of string leaves an incomplete
  122.  *    command at the end of the buffer, then NULL is returned.
  123.  *
  124.  * Side effects:
  125.  *    If string leaves a command incomplete, the partial command
  126.  *    information is buffered for use in later calls to this procedure.
  127.  *    Once a command has been returned, that command is deleted from
  128.  *    the buffer on the next call to this procedure.
  129.  *
  130.  *----------------------------------------------------------------------
  131.  */
  132.  
  133. char *
  134. Tcl_AssembleCmd(buffer, string)
  135.     Tcl_CmdBuf buffer;        /* Token for a command buffer previously
  136.                  * created by Tcl_CreateCmdBuf.  */
  137.     char *string;        /* Bytes to be appended to command stream.
  138.                  * Note:  if the string is zero length,
  139.                  * then whatever is buffered will be
  140.                  * considered to be a complete command
  141.                  * regardless of whether parentheses are
  142.                  * matched or not. */
  143. {
  144.     register CmdBuf *cbPtr = (CmdBuf *) buffer;
  145.     int length, totalLength;
  146.     register char *p;
  147.  
  148.     /*
  149.      * If an empty string is passed in, just pretend the current
  150.      * command is complete, whether it really is or not.
  151.      */
  152.  
  153.     length = strlen(string);
  154.     if (length == 0) {
  155.     cbPtr->bytesUsed = 0;
  156.     return cbPtr->buffer;
  157.     }
  158.  
  159.     /*
  160.      * Add the new information to the buffer.  If the current buffer
  161.      * isn't large enough, grow it by at least a factor of two, or
  162.      * enough to hold the new text.
  163.      */
  164.  
  165.     length = strlen(string);
  166.     totalLength = cbPtr->bytesUsed + length + 1;
  167.     if (totalLength > cbPtr->bufSize) {
  168.     unsigned int newSize;
  169.     char *newBuf;
  170.  
  171.     newSize = cbPtr->bufSize*2;
  172.     if (newSize < totalLength) {
  173.         newSize = totalLength;
  174.     }
  175.     newBuf = (char *) ckalloc(newSize);
  176.     strcpy(newBuf, cbPtr->buffer);
  177.     ckfree(cbPtr->buffer);
  178.     cbPtr->buffer = newBuf;
  179.     cbPtr->bufSize = newSize;
  180.     }
  181.     strcpy(cbPtr->buffer+cbPtr->bytesUsed, string);
  182.     cbPtr->bytesUsed += length;
  183.  
  184.     /*
  185.      * See if there is now a complete command in the buffer.
  186.      */
  187.  
  188.     p = cbPtr->buffer;
  189.     while (1) {
  190.     int gotNewLine = 0;
  191.  
  192.     while (isspace(*p)) {
  193.         if (*p == '\n') {
  194.         gotNewLine = 1;
  195.         }
  196.         p++;
  197.     }
  198.     if (*p == 0) {
  199.         if (gotNewLine) {
  200.         cbPtr->bytesUsed = 0;
  201.         return cbPtr->buffer;
  202.         }
  203.         return NULL;
  204.     }
  205.     p = TclWordEnd(p, 0);
  206.     }
  207. }
  208.